export const conv2Tree = (data: any, id: string = 'id', pid: string = 'pid', root = '') => {
  if (!id) return console.warn('convert2Tree方法需要传入数据id')
  if (!pid) return console.warn('convert2Tree方法需要传入数据pid')
  let cache: any = {}
  data.forEach((item: any) => {
    item.children = []
    if (item[id]) {
      cache[item[id]] = item
    }
  })
  return data.filter((item: any) => {
    if (item[pid] && item[pid] !== root) {
      if (item[pid] && cache[item[pid]]) cache[item[pid]].children.push(item)
      return false
    }
    return true
  })
}

interface KeyValue<T = any> {
  [key: string]: T
}
export const filterTree = ({
  value,
  data,
  prop,
  filter,
  filterXor,
  children,
  visible,
  filterChildren = true,
  callback,
}: KeyValue) => {
  // 默认赋值
  visible = visible || 'visible'
  children = children || 'children'
  prop = prop || 'text'

  const filterNodeMethod = function (value: any, data: any) {
    if (!value) {
      return true
    }
    let flag = (data[prop] || '').indexOf(value) !== -1
    return filterXor ? !flag : flag
  }

  const traverse = function (node: any) {
    const childNodes = node[children] || []

    childNodes.forEach((child: any) => {
      callback && callback(child)
      child[visible] = (!node.root && !filterChildren && node[visible]) || filterNodeMethod.call(child, value, child, prop)
      traverse(child)
    })

    if (!node[visible] && childNodes.length) {
      let allHidden = true
      allHidden = !childNodes.some((child: any) => child[visible])

      node[visible] = allHidden === false
    }
    if (!value) {
    }
  }
  let totalData: any = {
    root: true,
  }
  totalData[children] = data
  traverse(totalData)

  if (filter) {
    let copyData = data.slice()
    let filterHandle = (filterData: any) => {
      return filterData.filter((item: any, index: any) => {
        if (item[visible]) {
          if (item[children]) {
            item[children] = filterHandle(item[children])
          }
          return true
        }
        return false
      })
    }
    return filterHandle(copyData)
  }
}

/**
 * 扁平数据转树
 * @param data 数据对象
 * @param id 数据的id
 * @param pid 父元素id
 *
 */
export const initTree = (data: [], id = 'id', pid = 'pid', root = '') => {
  const cache = {}
  data.forEach((it) => {
    cache[it[id]] = it
  })

  const res = []
  data.forEach((it) => {
    const parent = cache[it[pid]]
    if (parent) (parent.children || (parent.children = [])).push(it)
    else res.push(it)
  })
  return res
}

// 扁平数据转为多选树
export const toNodeTree = (source, id, pidd) => {
  if (!id) return console.warn('toNodeTree方法需要传入数据key')
  if (!pidd) return console.warn('toNodeTree方法需要传入数据父的字段')
  let ckkeys = []
  let exkeys = []

  function fn(data, pid) {
    var result = [],
      temp
    for (var i = 0; i < data.length; i++) {
      if (data[i]['checked'] && !ckkeys.includes(data[i][id])) {
        ckkeys.push(data[i][id])
      } else if (!data[i].checked) {
        let idx = ckkeys.indexOf(data[i][pidd])
        if (idx != -1) ckkeys.splice(idx, 1)
      }

      if (data[i][pidd] == pid) {
        var obj = JSON.parse(JSON.stringify(data[i]))
        temp = fn(data, data[i][id])
        if (temp.length > 0) {
          obj.children = temp
          exkeys.push(obj[id])
          //有子节点则不设置选中
          // ckkeys.splice(ckkeys.indexOf(obj[id]), 1)

          const flag = obj.children.every((row) => row.checked)
          obj.checked = flag
          if (!flag) {
            ckkeys.splice(ckkeys.indexOf(obj[id]), 1)
          }
        }
        result.push(obj)
      }
    }
    return result
  }
  const tree = fn(source, '0')
  return { tree, exkeys, ckkeys }
}
// 扁平数据转为多选树
export const formatNodeTree = (source, id, pidd) => {
  if (!id) return console.warn('formatNodeTree方法需要传入数据key')
  if (!pidd) return console.warn('formatNodeTree方法需要传入数据父的字段')
  let ckkeys = [] //回显选中数据
  let exkeys = [] //回显展开数据

  function fn(data, pid) {
    const fatherNode = data.filter((item) => item[pidd] == pid)
    const childNode = data.filter((item) => item[pidd] != pid)
    // 所有子节点集合
    const NodeList = childNode.reduce((pre: Object, cur: Object) => {
      if (pre.hasOwnProperty(cur[pidd])) pre[cur[pidd]].push(cur)
      if (!pre.hasOwnProperty(cur[pidd])) pre[cur[pidd]] = [cur]
      if (cur && cur.checked && !ckkeys.includes(cur[id])) ckkeys.push(cur[id])
      return pre
    }, {} as object)

    // 组合成树
    fatherNode.forEach((it: any) => {
      let children = []
      if (NodeList.hasOwnProperty(it[id])) children = NodeList[it[id]]
      it.children = children
      exkeys.push(it[id])
      // 是否选中父
      const flag = children.every((row) => row.checked)
      it.checked = flag
      if (flag && !ckkeys.includes(it[id])) ckkeys.push(it[id])
      if (!flag && ckkeys.includes(it[id])) ckkeys.splice(ckkeys.indexOf(it[id]), 1)
    })
    return fatherNode
  }
  const tree = fn(source, '0')
  return { tree, exkeys, ckkeys }
}
